home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / QT MovieToolBox / pictmovier.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-19  |  17.9 KB  |  681 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        PictMovier.c
  3.  
  4.     Contains:    Application to make a movie from PICTs with various processes
  5.     
  6.     Written by:    Mark Krueger
  7.     Copyright:    © 1990-1991 by Apple Computer, Inc., all rights reserved.
  8.  
  9.         This example shows how you can make movies by doing processing on pictures.
  10.     
  11.     This allows a process that takes a long time to be shown at much faster rates
  12.     as a QuickTime movie. Any type of processing can be done, such as filtering, 
  13.     transitions, 3-D transformations. This example shows two trivial examples.
  14.     
  15.     The first simple does a linear cross fade between two images. The second creates
  16.     a random dot stereogram ( an image that if you stare at it long enough you can
  17.     see three dimensional depth in ( without special glasses ). This works from a single
  18.     image and shows how the effect can be varied from frame to frame.
  19.     
  20.     Note that the code is not necessarily well commented, but should prove useful as 
  21.     a jumping off point for making your own movie creation applications.
  22.     
  23.     Change History:
  24.     Friday, June 5, 1992 3:27:34 PM    MHK    New Today
  25.     Nov. 16th, 1993    RMF - Merged into this program ImportExportMovie.c example, 
  26.                           and added options for selecting effect for PiictMovier.c and show preview
  27.     Jan  17th, 194    RMF - Added option to append movie to existing movie (see DoMovie()).
  28.       
  29. */
  30.  
  31. #include "gGlobals.h"
  32.  
  33. #include    <pascal.h>
  34. #include    <Scrap.h>
  35. #include    <Desk.h>
  36. #include    <string.h>
  37. #include    <stdio.h>
  38. #include    <Fonts.h>
  39. #include    <Math.h>
  40.  
  41.     
  42. void DoRoll(long stageNum,long totalStages, int direction, int rollfill);
  43. CWindowPtr    MakeSWindow(Rect *frame,StringPtr name,GWorldPtr buffer);
  44.  
  45. /*
  46.     Close a window
  47.     
  48. */
  49. DoClose(WindowPtr wind)
  50. {
  51.     if ( wind == nil)    return(0);
  52.     if ( gActiveWindow == wind )    gActiveWindow = nil;
  53.         
  54.     if ( wind == (WindowPtr)gSrcWindow ) {
  55.         DoClear();
  56.         gSrcWindow = nil;
  57.         DisposeGWorld(gWorld);
  58.         gWorld = nil;
  59.     } else
  60.     if ( wind == (WindowPtr)gAltWindow ) { 
  61.         DoClear();
  62.         gAltWindow = nil;
  63.         DisposeGWorld(gAltWorld);
  64.         gAltWorld = nil;
  65.     } else
  66.     if ( wind == (WindowPtr)gDstWindow ) { 
  67.         gDstWindow = nil;
  68.         }
  69.     CloseWindow(wind);
  70.     return(0);
  71. }
  72.  
  73.  
  74.  
  75. void DoStage(long stageNum,long totalStages,Boolean reverse)
  76. {
  77.  
  78.     switch ( gDoCrossFade ) {
  79.     case EFFECT_CrossFad:
  80.         DoCrossFade(stageNum,totalStages,reverse);
  81.         break;
  82.     case EFFECT_Roll_Left:
  83.     case EFFECT_Roll_Right:
  84.     case EFFECT_Roll_Down:
  85.     case EFFECT_Roll_Up:
  86.         DoRoll(stageNum,totalStages, gDoCrossFade - EFFECT_Roll_Left + 1, gDoRollFill);
  87.         break;
  88.     case EFFECT_StereoGram:
  89.         DoRandomDotStereogram(stageNum,totalStages,reverse);
  90.         break;
  91.         }
  92. }
  93.  
  94. /*********************************************
  95.  
  96.     This processing routine creates a random dot stereogram of the input picture.
  97.     The second picture is not used.
  98.     
  99.     
  100. ********************************************/
  101.  
  102. void DoRandomDotStereogram(long stageNum,long totalStages,Boolean reverse)
  103. {
  104.     /* StdFile stuff */
  105.     
  106.     CGrafPtr    savePort;
  107.     GDHandle    saveGD;
  108.     char         *ip,*rp,*pp,*opp,*qp;
  109.     char         *sip,*srp,*spp;
  110.     short        rowBytes;
  111.     short        sRowBytes;
  112.     char        mode = 1;
  113.     
  114.     /* for sepecifying compression */
  115.     
  116.     short        i,j,x,y,height,width;
  117.     unsigned char pix,spix,ppix,qpix;
  118.  
  119.     char        *lineBuf = nil;
  120.     char        *newLineBuf = nil;
  121.     char        *tLineBuf = nil;
  122.     unsigned long timeseed;
  123.  
  124.  
  125. #define    RDS_DEPTH_FACTOR_VARIES            // set this to increase depth as movie progresses
  126.  
  127. #define    RDS_STRIP_WIDTH_VARIES            // set this to increase repeat strip as movie progresses
  128.  
  129. // #define    RDS_NEW_SEED_EACH_FRAME            // set this to have a new random background for each frame 
  130.  
  131. #ifdef    RDS_NEW_SEED_EACH_FRAME
  132.     GetDateTime(×eed);
  133.     rand(time);
  134. #else
  135.     rand(1);
  136. #endif
  137.  
  138. #ifdef    RDS_DEPTH_FACTOR_VARIES
  139.     gDepthFactor = 1 + (stageNum * 64) / totalStages;
  140.     gDepthDecodeTabInted = false;
  141. #else
  142.     gDepthFactor = 16;
  143. #endif
  144.  
  145. #ifdef    RDS_STRIP_WIDTH_VARIES
  146.     gStripWidth = 32 + (stageNum * 256) / totalStages;
  147. #else
  148.     gStripWidth = 128;
  149. #endif
  150.  
  151.     GetGWorld(&savePort,&saveGD);
  152.      SetGWorld(gDstWorld,nil);
  153.     EraseRect(&gDstWorld->portRect);
  154.     width = gWorld->portRect.right - gWorld->portRect.left;
  155.     height = gWorld->portRect.bottom - gWorld->portRect.top;
  156.     LockPixels(gWorld->portPixMap);
  157.     sRowBytes  = (*gWorld->portPixMap)->rowBytes & 0x7fff;
  158.     sip  = GetPixBaseAddr(gWorld->portPixMap);
  159.     SetGWorld(gDstWorld,nil);
  160.     
  161.     LockPixels(gDstWorld->portPixMap);
  162.     rowBytes = (*gDstWorld->portPixMap)->rowBytes & 0x7fff;
  163.     ip = GetPixBaseAddr(gDstWorld->portPixMap);
  164.  
  165.     lineBuf = NewPtr(sRowBytes);
  166.     if ( lineBuf == nil ) {
  167.         Error("allocating line buffer",0);
  168.         goto done;
  169.     }
  170.     newLineBuf = NewPtr(rowBytes);
  171.     if ( newLineBuf == nil ) {
  172.         Error("allocating nline buffer",0);
  173.         goto done;
  174.     }
  175.     tLineBuf = NewPtr(sRowBytes);
  176.     if ( tLineBuf == nil ) {
  177.         Error("allocating tline buffer",0);
  178.         goto done;
  179.     }
  180.     SwapMMUMode(&mode);
  181.     if ( gDepth == 1 ) {
  182.     
  183.         rp = ip;
  184.         for(y=0; y<height; y++) {
  185.             pp = rp;
  186.             for(x=0;x<gStripWidth/8;x++,pp++)  {
  187.                 pix = 0;
  188.                 for ( i=0; i < 8; i++ ) { 
  189.                     pix <<= 1;
  190.                     if ( rand(0) % 5 == 0 )
  191.                         pix |= 1;
  192.                 }
  193.                 qp = pp;
  194.                 for ( j=0; j < width/gStripWidth; j++ ) {
  195.                     *qp = pix;
  196.                     qp += gStripWidth /8;
  197.                 }
  198.             }
  199.             rp += rowBytes;
  200.         }
  201.         rp = ip;
  202.         srp = sip;
  203.     
  204.     
  205.         for(y=0;y<height;y++) {
  206.             pp = rp;
  207.             spp = srp;
  208.             spp += gDepthFactor/8;
  209.             qp = pp;
  210.             BlockMove(pp,tLineBuf,sRowBytes);
  211.             qp = tLineBuf;
  212.             pp = qp;
  213.             qp += gDepthFactor/8;
  214.             
  215.             opp = newLineBuf;
  216.             for(x=0;x < width/8-gStripWidth/8;x++ ,pp++,qp++,opp++) {
  217.                 spix = *spp++;
  218.                 qpix = *qp;
  219.                 ppix = *pp;
  220.                 pix = 0;
  221.                 for ( i=0; i < 8; i++ ) { 
  222.                     pix <<= 1;
  223.                     if ( (spix & 0x80 ) )
  224.                         pix |= (qpix & 0x80) != 0 ? 1 : 0;
  225.                     else
  226.                         pix |= (ppix & 0x80) != 0 ? 1 : 0;
  227.                     spix <<= 1;
  228.                     ppix <<= 1;
  229.                     qpix <<= 1;
  230.                 }
  231.                 *opp = pix;
  232.                 *(pp+gStripWidth/8) = pix;
  233.             }
  234.             BlockMove(newLineBuf,rp+gStripWidth/8,rowBytes-gStripWidth/8);
  235.             rp += rowBytes;
  236.             srp += sRowBytes;
  237.         }
  238.     } else
  239.     
  240.     if ( gDepth == 8 || gDepth == 40 ) {
  241.     
  242.         rp = ip;
  243.  
  244.         for(y=0; y<height; y++) {
  245.             pp = rp;
  246.             for(x=0;x<gStripWidth;x++)  {
  247.                 *pp++ = rand(0);
  248.             }
  249.             rp += rowBytes;
  250.         }
  251.  
  252.         rp = ip;
  253.         srp = sip;    
  254.  
  255.         for(y=0;y<height;y++) {
  256.             pp = rp;
  257.             spp = srp;
  258.             spp += gStripWidth;
  259.     
  260.             qp = pp;
  261.             BlockMove(pp,tLineBuf,sRowBytes);
  262.             qp = tLineBuf;
  263.             pp = qp;
  264.             
  265.             opp = newLineBuf;
  266.             for(x=0;x < width-gStripWidth;x++ ,pp++,qp++,opp++) {
  267.                 spix = *spp++;
  268.                 ppix = *pp;
  269.                 
  270.                 pix = *(qp + DecodeDepth(spix));
  271.                 *opp = pix;
  272.                 *(pp+gStripWidth) = pix;
  273.             }
  274.             BlockMove(newLineBuf,rp+gStripWidth,rowBytes-gStripWidth);
  275.             rp += rowBytes;
  276.             srp += sRowBytes;
  277.         }
  278.     }
  279.     SwapMMUMode(&mode);
  280.      UnlockPixels(gDstWorld->portPixMap);
  281.  
  282.     SetGWorld(savePort,saveGD);
  283. done:
  284.     if ( newLineBuf )
  285.         DisposPtr(newLineBuf);
  286.     if ( lineBuf )
  287.         DisposPtr(lineBuf);
  288.     if ( tLineBuf )
  289.         DisposPtr(tLineBuf);
  290.     
  291.  
  292. }
  293.  
  294. /*********************************************
  295.  
  296.      a better random function than the one in the ROM 
  297.      
  298. *********************************************/
  299.  
  300. long rand(long reseed)
  301. {
  302. #define    A    16807
  303. #define    M    2147483647
  304. #define    Q    127773
  305. #define    R    2836
  306.  
  307.     static long seed = 1;
  308.  
  309.     long lo,hi,test;
  310.     
  311.     if ( reseed != 0 )
  312.         seed = reseed;
  313.     hi = seed / Q;
  314.     lo = seed % Q;
  315.     test = A*lo - R*hi;
  316.     if ( test > 0 ) 
  317.         seed = test;
  318.     else
  319.         seed = test + M;
  320.     return ( seed/(M>>16));
  321. }
  322.  
  323. unsigned char DecodeDepth(unsigned char pix)
  324. {
  325.     static unsigned char table[256];
  326.     short i;
  327.     
  328.     if ( !gDepthDecodeTabInted ) {
  329.         gDepthDecodeTabInted = 1;
  330.         for ( i=0; i < 255; i++ ) {
  331.             table[i] = (i * gDepthFactor)/255;
  332.         }
  333.     }
  334.     return(table[pix]);
  335. }
  336.  
  337. /*********************************************
  338.  
  339.     This processing routine does a linear cross dissolve between the two images,
  340.     using CopyBits with blend mode. It shows how to do a process which involves 
  341.     both images. Any type of process could be done here, using the three parameters
  342.     to determine how much of the processing has progressed.
  343.     
  344.     Note: See the Develop article by Konstantin Othmar ( sorry I forget the issue number )
  345.     about CopyBits to learn how to do other cool effects just using CopyBits.
  346.     
  347. *********************************************/
  348.  
  349. void DoCrossFade(long stageNum,long totalStages,Boolean reverse)
  350. {
  351.     GWorldPtr    saveWorld;
  352.     GDHandle    saveGD;
  353.     RGBColor     opColor;
  354.     
  355.     
  356.     if ( reverse )
  357.         opColor.red  = opColor.green  = opColor.blue  = (stageNum*0xffff)/totalStages;
  358.     else
  359.         opColor.red  = opColor.green  = opColor.blue  = ((totalStages-stageNum)*0xffff)/totalStages;
  360.     
  361.     GetGWorld(&saveWorld,&saveGD);
  362.  
  363.     SetGWorld(gDstWorld,nil);
  364.     CopyBits((BitMap *)*gAltWorld->portPixMap,(BitMap *)*gDstWorld->portPixMap,
  365.                 &gAltWorld->portRect,&gDstWorld->portRect,ditherCopy,nil);
  366.     OpColor(&opColor);
  367.     CopyBits((BitMap *)*gWorld->portPixMap,(BitMap *)*gDstWorld->portPixMap,
  368.                 &gWorld->portRect,&gDstWorld->portRect,blend,nil);
  369.     SetGWorld(saveWorld,saveGD);
  370.     
  371. }    /* End of () */
  372.  
  373. /*********************************************
  374.  
  375.     Create the movie by processing all the frames.
  376.     
  377. ********************************************/
  378. OSErr OpenCreateMovie(Boolean Append, Movie *gMovie, short *resRefNum, short *resID, SFReply *sfr)
  379. {    OSErr result;
  380.     FSSpec        mySpec;                            /* Data structure with filename, etc. */
  381.     
  382.     ClearMoviesStickyError();                    /* Clear any old errors */
  383.     result = FSMakeFSSpec(sfr->vRefNum, 0, (unsigned char *) sfr->fName, &mySpec);
  384.     if (result == fnfErr) result = 0;
  385.     
  386.     if (Append)     {        /* RMF */
  387.         //    Open a movie file using the FSSpec and create a movie from that file.
  388.         
  389.         result = OpenMovieFile(&mySpec, resRefNum, fsRdWrPerm);
  390.         if (result == noErr) {
  391.             result = NewMovieFromFile(gMovie,*resRefNum, resID, nil,newMovieActive, nil);
  392.             }
  393.     } else
  394.         result = CreateMovieFile(  &mySpec, 'TVOD',0,createMovieFileDeleteCurFile, resRefNum, gMovie);
  395.     return result;
  396. }    /* End of () */
  397.  
  398. CWindowPtr OpenReplaceMovieWindow(StringPtr name, short width, short height)
  399. {    Rect        rect;
  400.     if ( gDstWindow ) {
  401.         CloseWindow((WindowPtr)gDstWindow);
  402.         gDstWindow = nil;
  403.         }    
  404.     SetRect(&rect,80,80, width+80, height+80);
  405.     gDstWindow = MakeSWindow(&rect, name, nil);
  406.  
  407.     return gDstWindow;
  408. }    /* End of () */
  409.  
  410. OSErr DoMovie(Boolean Append)
  411. {    GWorldPtr    saveWorld;
  412.     GDHandle    saveGD;
  413.     short         resRefNum, resID = 0;
  414.     OSErr        result;
  415.  
  416.     /* Stuff for creating the file */
  417.  
  418.     SFReply        sfr;                            /* StdFile reply */
  419.     Movie        gMovie = 0;                            /* Our movie, track and media */
  420.     Track        gTrack, gTackOld;
  421.     Media        gMedia;
  422.     long         maxCompressedFrameSize;            /* Max size of compressed frame        */
  423.     long        compressedFrameSize;            /* Size of current compressed frame */
  424.     Handle        compressedFrameBitsH = nil;        /* Buffer for the compressed data    */
  425.     ImageDescription    **imageDescriptionH = nil;        /* Contains info about the sample    */
  426.     Ptr            data;
  427.     EventRecord myEvent;
  428.     ImageSequence    seq;
  429.     Rect        dstRect;
  430.     short        i, width,height;
  431.     
  432.     TimeValue     MyMediaDuration, timeLength, sampleDuration;
  433.     Boolean     foundVideo;
  434.     
  435.     GetGWorld(&saveWorld,&saveGD);
  436.  
  437.     /* Prompt the user for a file name and create it */
  438.     if (Append) {                /* RMF */
  439.         Point        where;
  440.         SFTypeList    typeList;
  441.         //---------------------------------------------------------------------------------------------
  442.         //    Ask for a source movie file using Standard Preview.
  443.         //    Use (-2,-2) to center on the best device.
  444.         //---------------------------------------------------------------------------------------------
  445.     
  446.         where.h = where.v = -2;
  447.         typeList[0] = 'MooV';
  448.         SFGetFilePreview(where,"\p", nil,1,typeList,nil, &sfr);
  449.     
  450.     } else {
  451.         static Str255    name = "\pMovieToolBox Movie";
  452.         Point        where;
  453.         where.h = where.v = -2;
  454.         SFPutFile(where, (StringPtr) "\pMovie file to create:",(StringPtr)name,nil,&sfr);
  455.         if (sfr.good) 
  456.             BlockMove(sfr.fName,name,sfr.fName[0]+1);
  457.         }
  458.     if (!sfr.good)    return;
  459.     
  460.     
  461.     width = gRect.right - gRect.left;
  462.     height = gRect.bottom - gRect.top;
  463.     if ( gOversample ) {
  464.         width /= 2;
  465.         height /= 2;
  466.         }
  467.         
  468.     if (OpenReplaceMovieWindow(sfr.fName, width, height) == nil) goto done;        /* Error opening window */
  469.         
  470.     imageDescriptionH = (ImageDescription **)NewHandle( sizeof( ImageDescription));    /* handle for image descriptor */
  471.     if ( imageDescriptionH == nil ) {
  472.         Error("Out of Memory",MemError());
  473.         goto done;
  474.     }
  475.     
  476.     result = OpenCreateMovie(Append, &gMovie, &resRefNum, &resID, &sfr);
  477.  
  478.     if (result == noErr) result = GetMoviesError();    
  479.     if (result != noErr) {
  480.         Error("Opening Movie file", result);    goto done;
  481.         }
  482.     
  483.             
  484.     /*    Find a movie's video track.    */
  485. // RMF
  486.     foundVideo = false;
  487.     for (i=1; ((i<=GetMovieTrackCount(gMovie)) && (!foundVideo)); i++) {
  488.         OSType                    myMediaType;
  489.         
  490.         gTrack = GetMovieIndTrack(gMovie, i);
  491.         gMedia = GetTrackMedia(gTrack);
  492.         GetMediaHandlerDescription(gMedia, &myMediaType, nil, nil);
  493.         if (myMediaType == VideoMediaType)
  494.             foundVideo = true;
  495.         }    /* End for() */
  496. // RMF
  497.     if (foundVideo == true)    {    
  498.         timeLength = GetMediaDuration(gMedia);    
  499.     } else {
  500.         timeLength = 0L;
  501.         
  502.         gTrack = NewMovieTrack(gMovie,(long)width<<16, (long)height<<16, 0 /* volume */);
  503.         gMedia = NewTrackMedia(gTrack, VideoMediaType, gStandardP.frameRate>>16L, nil,(OSType) nil);
  504.     //    SetMediaTimeScale(gMedia, 1);
  505.         }
  506.     BeginMediaEdits( gMedia );                                        /* adding samples to the media */
  507.     GetMaxCompressionSize(gAltWorld->portPixMap,&gAltWorld->portRect,
  508.                         gStandardP.depth,gStandardP.spatialQuality,
  509.                         gStandardP.theCodecType,gStandardP.theCodec,&maxCompressedFrameSize);    
  510.  
  511.     compressedFrameBitsH = NewHandle(maxCompressedFrameSize);    
  512.     if ( compressedFrameBitsH == nil ) {
  513.         Error("Out of Memory",MemError());    goto bail;
  514.         }
  515.         
  516.     GetGWorld(&saveWorld,&saveGD);                
  517.     SetGWorld((CGrafPtr)gDstWorld,nil);    PaintRect(&gDstWorld->portRect);
  518.     
  519.     if ( (result=CompressSequenceBegin(&seq,gDstWorld->portPixMap,nil,
  520.             &gDstWorld->portRect,nil,gStandardP.depth,gStandardP.theCodecType, 
  521.             gStandardP.theCodec,
  522.             gStandardP.spatialQuality,gStandardP.temporalQuality,gStandardP.keyFrameRate,
  523.             nil,codecFlagUpdatePreviousComp,imageDescriptionH)) != 0 ) {
  524.         Error("CompressSequenceBegin Failed. #",result);
  525.         goto bail2;
  526.         }
  527.         
  528.     SetGWorld(saveWorld,saveGD);
  529.     while ( WaitNextEvent( everyEvent, &myEvent, 0, nil) != 0 ) {
  530.         if ( HandleEvents(&myEvent) )     goto bail2;        /* RMF - was return; */
  531.         }
  532.     
  533.     
  534.     SetRect(&dstRect, 0,0, gRect.right/2, gRect.bottom/2);
  535.     i = GetMediaTimeScale(gMedia);    /*    durationPerSample    */
  536.     i = 1;
  537.     for ( gFrameNumber=0; gFrameNumber < gNumberSteps; gFrameNumber++ ) {
  538.         SetGWorld(saveWorld,saveGD);
  539.         if ( WaitNextEvent( everyEvent, &myEvent, 0, nil) != 0 ) {        /* Do background events... */
  540.             if ( HandleEvents(&myEvent) )    break;
  541.             }
  542.             
  543.         SetGWorld((CGrafPtr)gDstWorld,nil);
  544.         PaintRect(&gDstWorld->portRect);
  545.  
  546.         if ( gDstWorld && gWorld && gAltWorld )                         /* Draw the current stage in the buffer */
  547.             DoStage(gFrameNumber, gNumberSteps, gBackwards);
  548.  
  549.         SetGWorld((CGrafPtr)gDstWindow,nil);
  550.         InvalRect(&gDstWindow->portRect);
  551.         DoHLock(compressedFrameBitsH);
  552.         data = StripAddress(*compressedFrameBitsH);
  553.         
  554.         if ( gOversample )  {            /* use: gBufferWorld to create oversame image */
  555.             SetGWorld(gBufferWorld,nil);
  556.             CopyBits((BitMap *)*gDstWorld->portPixMap,(BitMap *)*gBufferWorld->portPixMap,
  557.                 &gDstWorld->portRect,&dstRect,ditherCopy,nil);
  558.         
  559.             result = CompressSequenceFrame(seq,gBufferWorld->portPixMap,&dstRect,
  560.                     codecFlagUpdatePreviousComp,data,&compressedFrameSize,nil,nil);
  561.         } else {
  562.             SetGWorld((CGrafPtr)gDstWorld,nil);
  563.             result = CompressSequenceFrame(seq,gDstWorld->portPixMap,&gDstWorld->portRect,
  564.                     codecFlagUpdatePreviousComp,data,&compressedFrameSize,nil,nil);
  565.             }
  566.             
  567.         if ( result ) {
  568.             Error("Compress Sequence Frame Failed. #",result);
  569.             break;
  570.             }
  571.             
  572.         DoHUnlock(compressedFrameBitsH);
  573.         
  574.         result = AddMediaSample(gMedia,
  575.                     compressedFrameBitsH, 0L,compressedFrameSize,
  576.                     (TimeValue) i,            /*    durationPerSample    */
  577.                     (SampleDescriptionHandle) imageDescriptionH,
  578.                     1L,    /* numberOfSamples */
  579.                     0,     /* sampleFlags */
  580.                     &sampleDuration);
  581.         if ( result ) {
  582.             Error("AddMediaSample Failed. #",result); break;
  583.             }
  584.             
  585.     }    /* End for() */
  586. bail2:
  587.     CDSequenceEnd(seq);
  588.     
  589. bail:
  590. {    TimeValue     test;
  591.  
  592.     MyMediaDuration = GetMediaDuration(gMedia);
  593.     test = -1;
  594.     result = InsertMediaIntoTrack(gTrack,
  595.                                     test,                /* -1 = at end, 0L = at start of Track */
  596.                                     timeLength,                        /* Media time */
  597.                                     MyMediaDuration - timeLength,    /* amount of data to insert */
  598.                                     1<<16);                            /* Media Rate */
  599.     if ( result ) {
  600.         Error("InsertMediaIntoTrack Failed. #",result);
  601.         }
  602.         
  603.     if (Append) {    
  604.         result = UpdateMovieResource(gMovie, resRefNum, resID, nil);
  605.     } else
  606.         result = AddMovieResource(gMovie, resRefNum, &resID, nil);
  607.     if ( result ) {
  608.         Error("AddMovieResource Failed. #",result);
  609.         }
  610.     EndMediaEdits( gMedia );                /* We're done adding samples */
  611.     }
  612. //    MakeFilePreview(resRefNum, (ProgressProcRecordPtr)-1L);        /* RMF */
  613.     
  614.     CloseMovieFile( resRefNum );
  615.  
  616. done: 
  617.     SetGWorld(saveWorld,saveGD);
  618.     if ( imageDescriptionH )    DoDisposHandle((Handle)imageDescriptionH);
  619.     if ( compressedFrameBitsH )    DoDisposHandle((Handle)compressedFrameBitsH);
  620.     if ( gMovie )                DisposeMovie(gMovie);    
  621.     if ( gDstWindow ) { 
  622.         CloseWindow((WindowPtr)gDstWindow);
  623.         gDstWindow  = nil;
  624.         }
  625.     SetGWorld(saveWorld,saveGD);
  626. }    /* End of DoMovie() */
  627.  
  628.  
  629.  
  630.  
  631.  
  632. /********************************************
  633.  
  634.     Update a window
  635.     
  636. ********************************************/
  637.  
  638. void DoUpdate(CWindowPtr wind)
  639. {    GWorldPtr    saveWorld,gw;
  640.     GDHandle    saveGD;
  641.     char        c[32];
  642.     
  643.     GetGWorld(&saveWorld,&saveGD);
  644.     if ( wind == gDstWindow ) {
  645.         BeginUpdate((WindowPtr)wind);
  646.         SetGWorld((CGrafPtr)wind,nil);
  647.         CopyBits((BitMap *)*gDstWorld->portPixMap,(BitMap *)*wind->portPixMap,
  648.                 &gDstWorld->portRect,&wind->portRect,ditherCopy,nil);
  649.         if ( gFrameNumber >= 0 ) {
  650.             MoveTo(20,20);
  651.             TextSize(12);
  652.             TextFace(bold);
  653.             TextMode(patBic);
  654.             NumToString(gFrameNumber+1,(StringPtr)&c);
  655.             DrawString((StringPtr)&c);
  656.             DrawString((StringPtr)"\p/");
  657.             NumToString(gNumberSteps+1,(StringPtr)&c);
  658.             DrawString((StringPtr)&c);
  659.             MoveTo(21,21);
  660.             TextMode(srcOr);
  661.             NumToString(gFrameNumber+1,(StringPtr)&c);
  662.             DrawString((StringPtr)&c);
  663.             DrawString((StringPtr)"\p/");
  664.             NumToString(gNumberSteps+1,(StringPtr)&c);
  665.             DrawString((StringPtr)&c);
  666.         }
  667.         EndUpdate((WindowPtr)wind);
  668.         SetGWorld(saveWorld,saveGD);
  669.         return;
  670.     }
  671.     SetGWorld(wind,nil);
  672.     gw = (GWorldPtr)GetWRefCon((WindowPtr)wind);
  673.     BeginUpdate((WindowPtr)wind);
  674.     CopyBits((BitMap *)*gw->portPixMap,(BitMap *)*wind->portPixMap,
  675.             &gw->portRect,&wind->portRect,ditherCopy,nil);
  676.     EndUpdate((WindowPtr)wind);
  677.     SetGWorld(saveWorld,saveGD);
  678. }    /* End of () */
  679.  
  680.  
  681.